package com.yanqu.road.server.manger.union;

import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eMailType;
import com.yanqu.road.entity.enums.eRedHotNotifyType;
import com.yanqu.road.entity.enums.union.trade.eUnionTradeEventType;
import com.yanqu.road.entity.enums.union.trade.eUnionTradeFinishType;
import com.yanqu.road.entity.enums.union.trade.eUnionTradeLogType;
import com.yanqu.road.entity.enums.union.trade.eUnionTradeRouteState;
import com.yanqu.road.entity.log.cross.LogUnionTradeEventReward;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.union.UnionInfo;
import com.yanqu.road.entity.union.UnionMember;
import com.yanqu.road.entity.union.UnionUpgradeInfo;
import com.yanqu.road.entity.union.trade.*;
import com.yanqu.road.logic.bussiness.union.UnionTradeBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.logic.calc.CalculationManager;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.config.UnionConfigMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 商会贸易（商贸）
 */
public class UnionTradeMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(UnionTradeMgr.class.getName());

    //unionUid   routeId
    private static Map<String, Map<Integer, UnionTradeTeamData>>    unionTradeTeamDataMap;   //商贸队伍

    public static final int ROUTE_OPEN_NUM_ONE_DAY = 1;    //路线每日开启次数，暂定

    @Override
    public boolean reloadData() throws Exception {
        unionTradeTeamDataMap = UnionTradeBussiness.getUnionTradeTeamDataMap();
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for(Map<Integer, UnionTradeTeamData> teamDataMap : unionTradeTeamDataMap.values()){
            for(UnionTradeTeamData teamData : teamDataMap.values()){
                if(teamData.isInsertOption()){
                    UnionTradeBussiness.addUnionTradeTeamData(teamData);
                }else if(teamData.isUpdateOption()){
                    UnionTradeBussiness.updateUnionTradeTeamData(teamData);
                }
            }
        }
        return true;
    }

    //获取商会商贸队伍
    public static Map<Integer, UnionTradeTeamData> getTeamDataMapByUnionUid(String unionUid){
        Map<Integer, UnionTradeTeamData> map = unionTradeTeamDataMap.get(unionUid);
        if(map == null){
            synchronized (unionTradeTeamDataMap) {
                map = unionTradeTeamDataMap.get(unionUid);
                if(map == null) {
                    map = new ConcurrentHashMap<>();
                    unionTradeTeamDataMap.put(unionUid, map);
                }
            }
        }
        return map;
    }

    //获取商贸路线队伍
    public static UnionTradeTeamData getTeamDataByUnionUinAndRouteId(String unionUid, int routeId){
        return getTeamDataMapByUnionUid(unionUid).get(routeId);
    }

    //是否已解锁路线
    public static boolean isRouteUnlock(UnionTradeRouteInfo routeInfo, UnionInfo unionInfo){
        return UnionConfigMgr.getUnionLv(unionInfo.getExperience()) >= Integer.valueOf(routeInfo.getUnlock());
    }

    //计算路线当前状态
    public static int calTradeRouteStateVal(UnionTradeRouteInfo routeInfo, UnionTradeTeamData tradeTeamData){
        if(tradeTeamData == null){
            return eUnionTradeRouteState.UnOpen.getIntValue();
        }
        //已结束的不再计算
        if(tradeTeamData.getStateVal() == eUnionTradeRouteState.Close.getIntValue()){
            return eUnionTradeRouteState.Close.getIntValue();
        }
        if(tradeTeamData.getStartTradeTime() == 0 && tradeTeamData.getOpenTime() > 0){
            return eUnionTradeRouteState.UnStart.getIntValue();
        }
        if(tradeTeamData.getStartTradeTime() > 0){
            long pass = DateHelper.getCurrentTime() / 1000 - tradeTeamData.getStartTradeTime();
            if(pass >= (routeInfo.getGoTime() + routeInfo.getReturnTime())){
                return eUnionTradeRouteState.Close.getIntValue();
            }else if(pass >= routeInfo.getGoTime()){
                return eUnionTradeRouteState.Back.getIntValue();
            }else{
                return eUnionTradeRouteState.Trade.getIntValue();
            }
        }
        return eUnionTradeRouteState.UnOpen.getIntValue();
    }

    //检查所有商会路线的状态（定时）
    public static void checkAllUnionTradeRouteState(){
        //logger.info(" check trade state start ");
        long startTimeMillis = System.currentTimeMillis();
        for(Map.Entry<String, Map<Integer, UnionTradeTeamData>>  unionRouteTeamDataEntry : unionTradeTeamDataMap.entrySet()){  //遍历商会
            String unionUid = unionRouteTeamDataEntry.getKey();
            boolean stateChange = false;
            for(Map.Entry<Integer, UnionTradeTeamData> routeTeamDataEntry: unionRouteTeamDataEntry.getValue().entrySet()){   //遍历商队
                int routeId = routeTeamDataEntry.getKey();
                UnionTradeRouteInfo routeInfo = UnionConfigMgr.getUnionTradeRouteInfo(routeId);
                UnionTradeTeamData unionTradeTeamData = routeTeamDataEntry.getValue();
                boolean thisRouteChange = checkTradeRouteState(routeInfo, unionTradeTeamData);
                if(!stateChange){    // 避免改变状态被覆盖
                    stateChange = thisRouteChange;
                }
            }
            if(stateChange){
                syncRouteCanJoinToMember(unionUid);
            }
        }
        logger.info(" check trade state end, cost {} ",  System.currentTimeMillis() - startTimeMillis);
    }

    private static boolean checkTradeRouteState(UnionTradeRouteInfo routeInfo, UnionTradeTeamData unionTradeTeamData) {
        boolean stateChange = false;
        synchronized (unionTradeTeamData){
            if(unionTradeTeamData.isSendReward()){
                return false;
            }
            if(unionTradeTeamData.getStateVal() == eUnionTradeRouteState.Close.getIntValue()){
                //改由玩家触发结算
                //但商会解散的情况,无人触发.
                if (unionTradeTeamData.getFinishType() == eUnionTradeFinishType.DeleteUnion.getIntValue()) {
                    //没有任何奖励
                    unionTradeTeamData.setSendReward(true);
                }
                return false;
            }
            int preState = unionTradeTeamData.getStateVal();
            int calState = calTradeRouteStateVal(routeInfo, unionTradeTeamData);
            if(preState != calState && calState == eUnionTradeRouteState.Back.getIntValue()){
                //开始返程计算预计商贸奖励
                calBackExpectReward(routeInfo, unionTradeTeamData);

                if(unionTradeTeamData.getTakeEventIndex() < (unionTradeTeamData.getEventTimeList().size() -1)){
                    //补触发特殊事件
                    triggerTradeEvent(unionTradeTeamData);
                }
            }else if(preState != calState && calState == eUnionTradeRouteState.Close.getIntValue()){
                //关服或者意外情况导致，重新触发事件及返程预计奖励计算
                if(StringUtils.isNullOrEmpty(unionTradeTeamData.getExpectReward())){
                    //预计奖励计算（补偿）
                    calBackExpectReward(routeInfo, unionTradeTeamData);
                }
                if(unionTradeTeamData.getTakeEventIndex() < (unionTradeTeamData.getEventTimeList().size() -1)){
                    //补触发特殊事件
                    triggerTradeEvent(unionTradeTeamData);
                }

                doNormalTradeFinishReward(routeInfo, unionTradeTeamData);
                //unionTradeTeamData.setStateVal(eUnionTradeRouteState.Close.getIntValue());
                //unionTradeTeamData.setFinishType(eUnionTradeFinishType.Normal.getIntValue());
            }else if(preState == calState && calState == eUnionTradeRouteState.Trade.getIntValue()){
                //商贸进行中，触发特殊事件
                triggerTradeEvent(unionTradeTeamData);
            }
            if(preState != calState){
                stateChange = true;
            }
        }
        return stateChange;
    }

    //返回，计算预计奖励（商会奖励比例=总赚钱/路线要求赚钱；玩家奖励=sum(门客赚钱/路线要求赚钱)）
    private static void calBackExpectReward(UnionTradeRouteInfo routeInfo, UnionTradeTeamData unionTradeTeamData) {
        unionTradeTeamData.setStateVal(eUnionTradeRouteState.Back.getIntValue());
        Property baseReward = PropertyHelper.parseStringToProperty(routeInfo.getRewards());  //路线奖励
        Property unionReward = new Property();      //商会奖励
        Property playerReward = new Property();     //玩家奖励
        Property expectReward = new Property();     //预期奖励
        //门客总赚钱
        long allEarn = 0L;
        List<UnionTradeTeamUserJoin> joinDataList = unionTradeTeamData.getUserJoinDataList();
        for(UnionTradeTeamUserJoin joinData : joinDataList){
            //if(joinData.isQuit()) {   //退出也有奖励
            //   continue;
            //}
            allEarn = allEarn + joinData.getPatronsEarn();
            if(allEarn - routeInfo.getCondition() <= 0){
                BigDecimal completePercent = BigDecimal.valueOf(joinData.getPatronsEarn()).divide(BigDecimal.valueOf(routeInfo.getCondition()), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                calExpectReward(baseReward, playerReward, completePercent);
            }else{
                long lastEarn = allEarn - joinData.getPatronsEarn();
                BigDecimal completePercent = BigDecimal.valueOf(routeInfo.getCondition() - lastEarn).divide(BigDecimal.valueOf(routeInfo.getCondition()), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                calExpectReward(baseReward, playerReward, completePercent);
                break;
            }
        }
        //商会奖励
        if(allEarn < routeInfo.getCondition()){
            BigDecimal completePercent = BigDecimal.valueOf(allEarn).divide(BigDecimal.valueOf(routeInfo.getCondition()), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
            long count = BigDecimal.valueOf(baseReward.getCountByGoodsId(GameConfig.GAME_ITEM_UNION_EXP).longValue()).multiply(
                    BigDecimal.valueOf(Math.min(1.0, completePercent.doubleValue()))).setScale(0, BigDecimal.ROUND_UP).longValue();
            unionReward.addProperty(GameConfig.GAME_ITEM_UNION_EXP, BigInteger.valueOf(count));
        }else{
            unionReward.addProperty(GameConfig.GAME_ITEM_UNION_EXP, baseReward.getCountByGoodsId(GameConfig.GAME_ITEM_UNION_EXP));
        }
        expectReward.addProperty(unionReward);
        expectReward.addProperty(playerReward);
        unionTradeTeamData.setExpectReward(PropertyHelper.parsePropertyToString(expectReward));
        addLogData(unionTradeTeamData, eUnionTradeLogType.TradeBack, null, null, DateHelper.getCurrentTime(),null);
    }

    private static void calExpectReward(Property baseReward, Property resultReward, BigDecimal completePercent) {
        for (Integer goodsId : baseReward.getGoods().keySet()) {
            if (goodsId.intValue() == GameConfig.GAME_ITEM_UNION_EXP) {
                continue;
            }
            long count = BigDecimal.valueOf(baseReward.getCountByGoodsId(goodsId).longValue()).multiply(
                    BigDecimal.valueOf(Math.min(1.0, completePercent.doubleValue()))).setScale(0, BigDecimal.ROUND_UP).longValue();
            resultReward.addProperty(goodsId, BigInteger.valueOf(count));
        }
    }

    //触发商贸事件
    private static void triggerTradeEvent(UnionTradeTeamData unionTradeTeamData) {
        int index = unionTradeTeamData.getTakeEventIndex();
        long logTime = DateHelper.getCurrentTime();
        int count = 0;
        if(index < unionTradeTeamData.getEventTimeList().size() -1){
            for(index = index + 1; index < unionTradeTeamData.getEventTimeList().size(); index++){
                long gap = DateHelper.getCurrentSecond() - unionTradeTeamData.getStartTradeTime();
                if(gap >= unionTradeTeamData.getEventTimeList().get(index)){
                    count++;
                   int eventId = unionTradeTeamData.getEventList().get(index);
                    UnionTradeEventInfo eventInfo = UnionConfigMgr.getUnionTradeEventInfo(eventId);
                    addLogData(unionTradeTeamData, eUnionTradeLogType.RandomEvent, null, eventInfo, logTime, null);
                }
            }
            if(count > 0) {
                unionTradeTeamData.setTakeEventIndex(count + unionTradeTeamData.getTakeEventIndex());
            }
        }
    }

    //处理正常贸易的奖励
    private static void doNormalTradeFinishReward(UnionTradeRouteInfo routeInfo, UnionTradeTeamData unionTradeTeamData){
        long currentTime = DateHelper.getCurrentTime();
        //汇总玩家事件奖励
        Map<Long, Property> userEventRewardMap = sumRouteEventRewardOfUser(unionTradeTeamData);
        //汇总商会事件奖励
        Property unionEventReward = sumRouteEventRewardOfUnion(unionTradeTeamData);

        Property allTradeReward = new Property();  //汇总商贸奖励
        Property allEventReward = new Property();  //汇总事件奖励
        //计算商贸奖励（按比例）
        Map<Long, Property> userTradeRewardMap = calRouteTradeRewardOfUser(routeInfo, unionTradeTeamData);
        Set<Long> sendedUserSet = new HashSet<>();
        for(Long userId : userTradeRewardMap.keySet()){
            sendedUserSet.add(userId);
            Property userReward = new Property();
            userReward.addProperty(userTradeRewardMap.get(userId));
            userReward.addProperty(userEventRewardMap.get(userId));    //事件

            allTradeReward.addProperty(userTradeRewardMap.get(userId));   //统计
            allEventReward.addProperty(userEventRewardMap.get(userId));
            sendPlayReward(userId, userReward, MailManager.UNION_TRADE_NORMAL_REWARD_SEND_TITLE, MailManager.UNION_TRADE_NORMAL_REWARD_SEND_CONTENT, routeInfo.getName());
            //DataAnalyticsMgr.trackOreWarGetRoadReward(userId,routeInfo.getId());
        }
        //其他玩家的事件奖励
        for(Long userId : userEventRewardMap.keySet()){
            if(!sendedUserSet.contains(userId)){
                allEventReward.addProperty(userEventRewardMap.get(userId));
                sendPlayReward(userId, userEventRewardMap.get(userId), MailManager.UNION_TRADE_NORMAL_REWARD_SEND_TITLE, MailManager.UNION_TRADE_NORMAL_REWARD_SEND_CONTENT, routeInfo.getName());
            }
        }

        Property unionReward = new Property();  //商会奖励
        Property expectReward = PropertyHelper.parseStringToProperty(unionTradeTeamData.getExpectReward());
        unionReward.addProperty(GameConfig.GAME_ITEM_UNION_EXP, expectReward.getCountByGoodsId(GameConfig.GAME_ITEM_UNION_EXP));        //商会经验
        allTradeReward.addProperty(unionReward);
        unionReward.addProperty(unionEventReward);

        //商会经验
        UnionMgr.addUnionExp(unionTradeTeamData.getUnionUid(), unionReward.getCountByGoodsId(GameConfig.GAME_ITEM_UNION_EXP).longValue(), eLogMoneyType.Union, eLogMoneyType.UnionTradeReward);

        allEventReward.addProperty(unionEventReward);
        finishRouteReward(unionTradeTeamData, allTradeReward, allEventReward);

        //运营日志
        String unionUid = unionTradeTeamData.getUnionUid();
        for(Long userId : userEventRewardMap.keySet()){  //玩家事件
            AutoLogMgr.add(new LogUnionTradeEventReward(unionUid, userId, routeInfo.getId(), PropertyHelper.parsePropertyToString(userEventRewardMap.get(userId)), eUnionTradeEventType.Player.getIntValue()));
        }
        if(!unionEventReward.isNothing()) {
            AutoLogMgr.add(new LogUnionTradeEventReward(unionUid, 0L, routeInfo.getId(), PropertyHelper.parsePropertyToString(unionEventReward), eUnionTradeEventType.UnionTeam.getIntValue()));
        }
    }

    //计算玩家商贸奖励
    private static Map<Long, Property> calRouteTradeRewardOfUser(UnionTradeRouteInfo routeInfo, UnionTradeTeamData unionTradeTeamData) {
        //userId
        Map<Long, Property> result = new HashMap<>();
        //队伍详情
        List<UnionTradeTeamUserJoin> unionTradeTeamUserJoinDataList =  unionTradeTeamData.getUserJoinDataList();
        //门客总赚钱
        long allEarn = 0L;
        Property baseReward = PropertyHelper.parseStringToProperty(routeInfo.getRewards());
        //过滤掉商会经验,不分摊给个人玩家
        baseReward.setGood(GameConfig.GAME_ITEM_UNION_EXP, BigInteger.ZERO);
        for(UnionTradeTeamUserJoin userJoinData : unionTradeTeamUserJoinDataList) {
            allEarn = allEarn + userJoinData.getPatronsEarn();   //总赚钱
        }
        if(allEarn > routeInfo.getCondition()){
            allEarn = routeInfo.getCondition();
        }
        long allEarn2 = 0L;
        for(UnionTradeTeamUserJoin userJoinData : unionTradeTeamUserJoinDataList) {
            allEarn2 = allEarn2 + userJoinData.getPatronsEarn();
            if(allEarn2 - routeInfo.getCondition() <= 0){
                BigDecimal completePercent = BigDecimal.valueOf(userJoinData.getPatronsEarn()).divide(BigDecimal.valueOf(routeInfo.getCondition()), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                calTradeReward(result, baseReward, userJoinData, completePercent);
            }else{
                long lastEarn = allEarn2 - userJoinData.getPatronsEarn();
                BigDecimal completePercent = BigDecimal.valueOf(allEarn - lastEarn).divide(BigDecimal.valueOf(routeInfo.getCondition()), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                calTradeReward(result, baseReward, userJoinData, completePercent);
                break;
            }
        }
        return  result;
    }

    //按比例计算派遣门客的商贸奖励
    private static void calTradeReward(Map<Long, Property> result, Property expectReward, UnionTradeTeamUserJoin userJoinData, BigDecimal completePercent) {
        Property userReward = new Property();
        for (Integer goodsId : expectReward.getGoods().keySet()) {
            if(expectReward.getCountByGoodsId(goodsId).compareTo(BigInteger.ZERO) <= 0){
                continue;
            }
            long count = BigDecimal.valueOf(expectReward.getCountByGoodsId(goodsId).longValue()).multiply(
                    BigDecimal.valueOf(Math.min(1.0, completePercent.doubleValue()))).setScale(0, BigDecimal.ROUND_UP).longValue();
            userReward.addProperty(goodsId, BigInteger.valueOf(count));
        }
        if (result.get(userJoinData.getUserId()) == null) {
            result.put(userJoinData.getUserId(), userReward);
        } else {
            result.get(userJoinData.getUserId()).addProperty(userReward);
        }
    }

    //汇总商会事件奖励
    private static Property sumRouteEventRewardOfUnion(UnionTradeTeamData unionTradeTeamData) {
        Property result = new Property();
        List<UnionTradeLog> logDataList = unionTradeTeamData.getLogDataList();
        for(UnionTradeLog logData : logDataList) {
            if (!isEventLogData(logData.getEventId())) {  //跳过非事件日志
                continue;
            }
            UnionTradeEventInfo eventInfo = UnionConfigMgr.getUnionTradeEventInfo(logData.getEventId());
            if (eventInfo.getType() == eUnionTradeEventType.Player.getIntValue()) {
                continue;                    //跳过玩家事件
            }
            Property reward = PropertyHelper.parseStringToProperty(eventInfo.getRewards());
            result.addProperty(reward);
        }
        return result;
    }
    //是否事件日志
    public static boolean isEventLogData(int eventId){
        return eventId > 1000;
    }

    //汇总玩家事件奖励
    private static Map<Long, Property> sumRouteEventRewardOfUser(UnionTradeTeamData unionTradeTeamData) {
        Map<Long, Property> result = new HashMap<>();
        List<UnionTradeLog> logDataList = unionTradeTeamData.getLogDataList();
        for(UnionTradeLog logData : logDataList){
            if(!isEventLogData(logData.getEventId())){          //跳过非事件日志
                continue;
            }
            UnionTradeEventInfo eventInfo = UnionConfigMgr.getUnionTradeEventInfo(logData.getEventId());
            if(eventInfo.getType() == eUnionTradeEventType.UnionTeam.getIntValue()){
                continue;                            //跳过商会事件
            }
            Property reward = PropertyHelper.parseStringToProperty(eventInfo.getRewards());
            for(Long userId : logData.getEventUserIdsList()){
                //if(quitUserList.contains(userId)){   //退出玩家改为有奖励
                //    continue;
                //}
                if(result.get(userId) == null){
                    result.put(userId, new Property());
                }
                result.get(userId).addProperty(reward);
            }
        }
        return result;
    }

    //获取队伍玩家
    public static Set<Long> getUserIdSet(List<UnionTradeTeamUserJoin> joinList){   //不区分玩家是否退出
        Set<Long> set = new HashSet<>();
        for(UnionTradeTeamUserJoin join : joinList){
            set.add(join.getUserId());
        }
        return set;
    }

    private static void finishRouteReward(UnionTradeTeamData unionTradeTeamData, Property tradeReward, Property eventReward){
        unionTradeTeamData.setReward(PropertyHelper.parsePropertyToString(tradeReward));
        unionTradeTeamData.setEventReward(PropertyHelper.parsePropertyToString(eventReward));
        unionTradeTeamData.setStateVal(eUnionTradeRouteState.Close.getIntValue());
        unionTradeTeamData.setFinishType(eUnionTradeFinishType.Normal.getIntValue());
        unionTradeTeamData.setSendReward(true);
    }

    //发送玩家奖励
    private static void sendPlayReward(long userId, Property userReward,String mailTitle, String mailContent, String routeName){
        UserInfo userInfo = UserMgr.getUserInfo(userId);
        String title = MultipleLanguageMgr.getContent(mailTitle, userInfo.getLanguage());
        String content = StringUtils.format(MultipleLanguageMgr.getContent(mailContent, userInfo.getLanguage()), MultipleLanguageMgr.getContent(routeName, userInfo.getLanguage()));
        MailManager.sendMail(userId, eMailType.DAILY.getValue(), PropertyHelper.parsePropertyToString(userReward), content, title);
    }

    public static void addLogData(UnionTradeTeamData unionTradeTeamData, eUnionTradeLogType logType, UserInfo userInfo) {
        addLogData(unionTradeTeamData, logType, userInfo, null, 0, null);
    }

    //添加商贸日志
    public static void addLogData(UnionTradeTeamData unionTradeTeamData, eUnionTradeLogType logType, UserInfo userInfo, UnionTradeEventInfo tradeEventInfo, long logTime, List<UnionTradeTeamUserJoin> newJoinDataList) {
        if(eUnionTradeLogType.OpenRoute.getIntValue() == logType.getIntValue()) {
            //记录路线开启日志
            UnionTradeLog logData = new UnionTradeLog();
            logData.setAddTime(unionTradeTeamData.getOpenTime());
            logData.setEventId(1);
            logData.addLogParams(userInfo.getNickName());
            unionTradeTeamData.addLogData(logData);
        }else if(eUnionTradeLogType.UserJoin.getIntValue() == logType.getIntValue() || eUnionTradeLogType.UserQuit.getIntValue() == logType.getIntValue()){
            UnionTradeLog logData = new UnionTradeLog();
            logData.addLogParams(userInfo.getNickName());
            if(eUnionTradeLogType.UserJoin.getIntValue() == logType.getIntValue()){
                logData.setEventId(2);
                logData.addLogParams(String.valueOf(newJoinDataList.size()));
            }else{
                logData.setEventId(4);
            }
            logData.setAddTime(logTime);
            unionTradeTeamData.addLogData(logData);
        }else if(eUnionTradeLogType.RandomEvent.getIntValue() == logType.getIntValue()){
            UnionTradeLog logData = new UnionTradeLog();
            logData.setAddTime(logTime);
            logData.setEventId(tradeEventInfo.getId());
            //随机人员
            int num = tradeEventInfo.getRewardsNum();
            Set<Long> teamMembers = getUserIdSet(unionTradeTeamData.getUserJoinDataList());
            List<Long> userIdList = getRandomNumFromCollection(teamMembers, num);
            List<String> userNameList = new ArrayList<>();
            for(Long userId : userIdList){
                userNameList.add(UserMgr.getNickName(userId));
            }
            if(tradeEventInfo.getType() == eUnionTradeEventType.Player.getIntValue()) {
                logData.addLogParams(StringUtils.listToString(userNameList, ","));
            }
            logData.setEventUserIdsList(userIdList);
            logData.addLogParams(tradeEventInfo.getRewards());
            unionTradeTeamData.addLogData(logData);
        }else if(eUnionTradeLogType.TradeBack.getIntValue() == logType.getIntValue()){
            UnionTradeLog logData = new UnionTradeLog();
            logData.setAddTime(logTime);
            logData.setEventId(3);
            logData.addLogParams(unionTradeTeamData.getExpectReward());
            unionTradeTeamData.addLogData(logData);
        }
    }

    //获取玩家在特定路线的派遣门客信息
    public static List<Integer> findPatronsByRouteIdAndUserId(String unionUid, int routeId, long userId){
        List<Integer> result = new ArrayList<>();
        UnionTradeTeamData unionTradeTeamData = getTeamDataByUnionUinAndRouteId(unionUid, routeId);
        if(unionTradeTeamData != null){
            List<UnionTradeTeamUserJoin> joinList =  unionTradeTeamData.getNewUserJoinDataList();
            for(UnionTradeTeamUserJoin userJoin : joinList){
                if(userJoin.getUserId() == userId){
                    result.add(userJoin.getPatronsId());
                }
            }
        }
        return result;
    }

    private static List<Long> getRandomNumFromCollection(Set<Long> teamMembers, int num) {
        if(num >= teamMembers.size()) {
            return new ArrayList<>(teamMembers);
        }
        List<Long> idList = new ArrayList<>();
        RandomHelper randomHelper = new RandomHelper();
        while (num > 0){
            Long val = (Long)randomHelper.randomList(teamMembers);
            idList.add(val);
            teamMembers.remove(val);
            num--;
        }
        return idList;
    }

    //通知用户退出商会
    public static void notifyUserQuitUnion(long userId, String unionUid){
        Map<Integer, UnionTradeTeamData>  tradeTeamDataMap = getTeamDataMapByUnionUid(unionUid);
        for(UnionTradeTeamData tradeTeamData : tradeTeamDataMap.values()){
            synchronized (tradeTeamData){
                int calState = calTradeRouteStateVal(UnionConfigMgr.getUnionTradeRouteInfo(tradeTeamData.getRouteId()), tradeTeamData);   //及时计算下
                if(calState != eUnionTradeRouteState.Trade.getIntValue() && calState != eUnionTradeRouteState.Back.getIntValue()){
                    continue;
                }
                int markQuit = 0;
                List<UnionTradeTeamUserJoin> userJoinDataList = tradeTeamData.getUserJoinDataList();
                Set<Long> teamUsers = getUserIdSet(userJoinDataList);
                if(!teamUsers.contains(userId)){
                    continue;
                }
                Iterator<UnionTradeTeamUserJoin> iterator = userJoinDataList.iterator();
                while (iterator.hasNext()){
                    UnionTradeTeamUserJoin userJoinData = iterator.next();
                    if(userId == userJoinData.getUserId()){
                        userJoinData.setQuit(true);                                                    //标记已退出
                    }
                    if(userJoinData.isQuit()){
                        markQuit++;
                    }
                }
                if(userJoinDataList.size() == markQuit){   //最后一个玩家退出，商贸继续
                    //tradeTeamData.setStateVal(eUnionTradeRouteState.Close.getIntValue());               //当没人时，结束贸易
                    //tradeTeamData.setFinishType(eUnionTradeFinishType.QuitUnion.getIntValue());         //退出导致的商贸结束
                }
                long time = DateHelper.getCurrentTime();
                addLogData(tradeTeamData, eUnionTradeLogType.UserQuit, UserMgr.getUserInfo(userId), null, time, null);
            }
        }
    }

    //通知商会解散
    public static void notifyUnionDelete(String unionUid){
        Map<Integer, UnionTradeTeamData>  tradeTeamDataMap = getTeamDataMapByUnionUid(unionUid);
        for(UnionTradeTeamData tradeTeamData : tradeTeamDataMap.values()) {
            synchronized (tradeTeamData) {
                int calState = calTradeRouteStateVal(UnionConfigMgr.getUnionTradeRouteInfo(tradeTeamData.getRouteId()), tradeTeamData);   //及时计算下
                if(calState != eUnionTradeRouteState.Trade.getIntValue() && calState != eUnionTradeRouteState.Back.getIntValue()) {
                    tradeTeamData.setFinishType(eUnionTradeFinishType.DeleteUnion.getIntValue());
                    continue;
                }
                tradeTeamData.setFinishType(eUnionTradeFinishType.DeleteUnion.getIntValue());
                tradeTeamData.setStateVal(eUnionTradeRouteState.Close.getIntValue());
            }
        }
    }

    //次数重置
    public static void resetOneDay(){
        for(Map.Entry<String, Map<Integer, UnionTradeTeamData>>  unionRouteTeamDataEntry : unionTradeTeamDataMap.entrySet()) {
            for (Map.Entry<Integer, UnionTradeTeamData> routeTeamDataEntry : unionRouteTeamDataEntry.getValue().entrySet()) {
                UnionTradeTeamData unionTradeTeamData = routeTeamDataEntry.getValue();
                synchronized (unionTradeTeamData) {
                    if (!DateHelper.isToday(new Date(unionTradeTeamData.getRestTime()))) {
                        unionTradeTeamData.setOpenNum(0);   //重置次数
                        unionTradeTeamData.setRestTime(System.currentTimeMillis());
                    }
                }
                resetData(unionTradeTeamData);  //暂时
            }
            //强制下发一次红点(作为补偿开启路线但未有派遣的情况等)
            syncRouteCanJoinToMember(unionRouteTeamDataEntry.getKey());
        }
    }

    public static void resetData(String unionUid){
        for (Map.Entry<Integer, UnionTradeTeamData> routeTeamDataEntry : getTeamDataMapByUnionUid(unionUid).entrySet()) {
            UnionTradeTeamData unionTradeTeamData = routeTeamDataEntry.getValue();
            resetData(unionTradeTeamData);
        }
    }

    //暂时，隔天重置数据，待客户端使用开启次数判定是否可以开启时去掉
    private static void resetData(UnionTradeTeamData unionTradeTeamData) {
        synchronized (unionTradeTeamData) {
            if (unionTradeTeamData.getStateVal() != eUnionTradeRouteState.Close.getIntValue()) {
                return;
            }
            if (unionTradeTeamData.getFinishType() == eUnionTradeFinishType.DeleteUnion.getIntValue()){
                return;     //解散的商会，路线不重置
            }
            if (!unionTradeTeamData.isSendReward()) {
                return;
            }
            if (unionTradeTeamData.getOpenTime() > LocalDateTimeHelper.getZeroTimeTimeStamp()) {
                //跳过当天开启
                return;
            }
            unionTradeTeamData.reset();
        }
    }

    public static void syncRouteCanJoinToMember(String unionUid){
        try {
            Map<Long, UnionMember> unionMemberMap = UnionMgr.getUnionMemberMap(unionUid);
            if(unionMemberMap == null){
                return;
            }
            for (long userId : unionMemberMap.keySet()) {
                syncRouteCanJoinToMember(unionUid, userId);
            }
        }catch (Exception e){
            logger.error("send union trade red hot error." + e.getMessage(), e);
        }
    }

    public static void syncRouteCanJoinToMember(String unionUid, long userId) {
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if (player != null) {
            boolean canJoin = hasRouteCanJoin(unionUid, player);
            WorldMessageProto.RedHotNotifyMsg.Builder redHotMsg = WorldMessagePb.parseRedHotNotifyMsg(eRedHotNotifyType.UnionTradeCanJoin.getValue(), canJoin == true ? 1 : 0, null);
            player.sendPacket(Protocol.U_RED_HOT_NOTIFY, redHotMsg);
        }
    }

    public static boolean hasRouteCanJoin(String unionUid, GamePlayer player) {
        //是否还有未派遣的门客
        int sendNum = 0;
        List<UserPatrons>  userPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
        for(UserPatrons userPatrons : userPatronsList){
            if(userPatrons.isUnionTradeSend()) {
                sendNum ++;
            }
        }
        if(sendNum == userPatronsList.size()){
            return false;   //无门客派遣   不能加入
        }
        boolean canJoin = false;
        UnionTradeTeamData teamData = null;
        Map<Integer, UnionTradeTeamData> unionTradeTeamDataMap = UnionTradeMgr.getTeamDataMapByUnionUid(unionUid);
        for(int routeId : unionTradeTeamDataMap.keySet()) {
            teamData = unionTradeTeamDataMap.get(routeId);
            synchronized (teamData){
                if (teamData.getStateVal() == eUnionTradeRouteState.UnStart.getIntValue()) {
                    canJoin = true;
                    break;
                }
                if (teamData.getStateVal() == eUnionTradeRouteState.Close.getIntValue() || teamData.getStateVal() == eUnionTradeRouteState.UnOpen.getIntValue()
                        || teamData.getStateVal() == eUnionTradeRouteState.Back.getIntValue()) {
                    //结束\未开启\返程均不能参加
                    continue;
                }
                //商贸中
                //人数上限
                Set<Long> userIdList = UnionTradeMgr.getUserIdSet(teamData.getUserJoinDataList());
                if (userIdList.contains(player.getUserId())) {
                    continue;   //已参与
                }
                UnionInfo unionInfo = UnionMgr.getUnionInfo(unionUid);
                UnionUpgradeInfo unionUpgradeInfo = UnionConfigMgr.getUnionUpgradeInfo(unionInfo.getExperience());
                if (unionUpgradeInfo == null) {
                    logger.error("union trade red hot sync, unionUpgradeInfo is null");
                    continue;
                }
                if (userIdList.size() >= unionUpgradeInfo.getMaxMemberCount()) {
                    continue;    //人数超了
                }
                //赚钱超了
                UnionTradeRouteInfo routeInfo = UnionConfigMgr.getUnionTradeRouteInfo(routeId);
                if (routeInfo != null) {
                    int len = teamData.getUserJoinDataList().size();
                    long allEarn = 0L;
                    for (int i = 0; i < len; i++) {
                        allEarn += teamData.getUserJoinDataList().get(i).getPatronsEarn();
                    }
                    if (allEarn < routeInfo.getCondition()) {
                        canJoin = true;
                        break;
                    }
                }
            }
        }
        return canJoin;
    }
}
